package com.LachesismStorm.lachesism.member.service.impl;


import com.LachesismStorm.lachesism.core.exception.Asserts;
import com.LachesismStorm.lachesism.core.service.RedisService;
import com.LachesismStorm.lachesism.core.util.CommonUtil;
import com.LachesismStorm.lachesism.core.util.JwtTokenUtil;
import com.LachesismStorm.lachesism.core.util.LachesismTools;
import com.LachesismStorm.lachesism.core.util.SendMessage;
import com.LachesismStorm.lachesism.member.dto.UmsMemberParam;
import com.LachesismStorm.lachesism.member.mapper.UmsUserMapper;
import com.LachesismStorm.lachesism.member.service.UmsMemberService;
import com.LachesismStorm.lachesism.member.util.MemberUtil;
import com.LachesismStorm.lachesism.member.vo.MemberDetails;
import com.LachesismStorm.lachesism.member.vo.UmsMember;
import com.LachesismStorm.lachesism.member.vo.dto.WeChatParam;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import static com.LachesismStorm.lachesism.core.common.enums.ResponseCodeEnum.NOTFOUND;
import static com.LachesismStorm.lachesism.websocket.WebSocketService.broadcast;


@Service
public class UmsMemberServiceImpl implements UmsMemberService {
    @Resource
    private UmsUserMapper umsUserMapper;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private RedisService redisService;

    @Value("${aes.key}")
    private String key;

    @Value("${wechat.appID}")
    private String appID;

    @Value("${wechat.appSecret}")
    private String appSecret;

    @Value("${file.tyre.address}")
    private String tyreAddress;

    @Value("${url.pc}")
    private String webUrl;


    @Override
    public UmsMember getUserInfo() {
        Integer userId = MemberUtil.getUserId();
        return umsUserMapper.getUserInfo(userId);
    }

    @Override
    public void updateMemberInfo(UmsMember member) {
        umsUserMapper.updateMemberInfo(member);
    }

    public String loginByOpenId(String openId) {
        UmsMember member = umsUserMapper.getUserByOpenId(openId);
        if (member != null) {
            MemberDetails memberDetails = new MemberDetails(member);
            return jwtTokenUtil.generateToken(memberDetails);
        } else {
            Asserts.fail("用户不存在");
            return null;
        }
    }

    @Override
    public WeChatParam getWeChatInfoByCode(WeChatParam param) {
        String phoneInfo = getPhoneNumber(param.getCode());
        WeChatParam weChatParam = new WeChatParam();
        weChatParam.setCode(param.getCode());
        weChatParam.setPhone(phoneInfo);
        return weChatParam;
    }

    @Override
    public String loginWithPhoneInfo(WeChatParam param) {
        if (param.getPhone() == null || param.getCode() == null) {
            Asserts.fail("请先获取微信授权信息");
            return null;
        }
        String openId = getOpenId(param.getCode());
        UmsMember member = new UmsMember();
        member.setOpneid(openId);
        member.setPhone(param.getPhone());
        return register(member);
    }


    @Override
    public UserDetails loadUserByUsername(String phone) {
        UmsMember member = umsUserMapper.getMemberInfo(phone);
        if (member != null) {
            return new MemberDetails(member);
        }
        return null;
    }


    public String register(UmsMember member) {
        Integer userExists = umsUserMapper.getUserExists(member);
        if (userExists != null && userExists > 0) {
            return loginByOpenId(member.getOpneid());
        } else {
            member.setNickname("微信用户" + member.getPhone().substring(6));
            member.setPassword(passwordEncoder.encode(member.getPhone()));
            member.setIcon(webUrl+"image/user.png");
            umsUserMapper.register(member);
            UmsMember memberInfo = umsUserMapper.getUserByOpenId(member.getOpneid());
            MemberDetails memberDetails = new MemberDetails(memberInfo);
            return jwtTokenUtil.generateToken(memberDetails);
        }

    }


    private String getOpenId(String code) {
        String urlString = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appID + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
        String result = CommonUtil.httpsRequest(urlString, "GET", null);
        Map<String, String> parse = JSON.parseObject(result, new TypeReference<Map<String, String>>() {
        });
        return parse.get("openid");
    }

//    private String getOpenId(String code) {
//        String token = getToken();
//        String urlString = "https://api.weixin.qq.com/wxa/getpluginopenpid?access_token=" + token;
//        JSONObject json = new JSONObject();
//        json.put("code", code);
//        String result = CommonUtil.httpsRequest(urlString, "POST", json.toString());
//        Map<String, String> parse = JSON.parseObject(result, new TypeReference<Map<String, String>>() {
//        });
//        System.out.println(result);
//        return parse.get("openpid");
//    }

    private String getPhoneNumber(String code) {
        String token = getToken();
        String urlString = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + token;
        JSONObject json = new JSONObject();
        json.put("code", code);
        String result = CommonUtil.httpsRequest(urlString, "POST", json.toString());
        Map<String, String> parse = JSON.parseObject(result, new TypeReference<Map<String, String>>() {
        });
        System.out.println(parse);
        return parse.get("phone_info");
    }

    public String getToken() {
        String token = (String) redisService.getWithTimeout("token");
        if (token == null || token.equals("")) {
            String accessToken = getStableAccessToken();
            setAccessToken(accessToken);
            return accessToken;
        }
        return token;
    }

    private String getAccessToken() {
        String urlString = "https://api.weixin.qq.com/cgi-bin/token";
        JSONObject json = new JSONObject();
        json.put("grant_type", "client_credential");
        json.put("appid", appID);
        json.put("secret", appSecret);
        String result = CommonUtil.httpsRequest(urlString, "POST", json.toString());
        Map<String, String> parse = JSON.parseObject(result, new TypeReference<Map<String, String>>() {
        });
        return parse.get("access_token");
    }

    private String getStableAccessToken() {
        String urlString = "https://api.weixin.qq.com/cgi-bin/stable_token";
        JSONObject json = new JSONObject();
        json.put("grant_type", "client_credential");
        json.put("appid", appID);
        json.put("secret", appSecret);
        String result = CommonUtil.httpsRequest(urlString, "POST", json.toString());
        Map<String, String> parse = JSON.parseObject(result, new TypeReference<Map<String, String>>() {
        });
        String token = parse.get("access_token");
        return token;
    }

    private void setAccessToken(String token) {
        redisService.set("token", token, 2, TimeUnit.HOURS);
    }

}